package ldap

import (
	"encoding/json"
	"errors"
	"fmt"

	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/connector/orm"
	"gitee.com/wuzheng0709/backend-gopkg/infrastructure/pkg/gin/log"

	"github.com/go-ldap/ldap/v3"
)

/*
@Author : lanyulei
*/
type SysSettings struct {
	orm.CommonModel
	Classify int             `gorm:"column:classify; type:int(11)" json:"classify" form:"classify"` // 设置分类，1 配置信息，2 Ldap配置
	Content  json.RawMessage `gorm:"column:content; type:json" json:"content" form:"content"`       // 配置内容
}

func getLdapFields() (ldapFields []map[string]string, err error) {
	var (
		settingsValue SysSettings
		contentList   []map[string]string
	)

	err = orm.GetMysqlDB().Model(&SysSettings{}).Where("classify = 2").Find(&settingsValue).Error
	if err != nil {
		return
	}

	err = json.Unmarshal(settingsValue.Content, &contentList)
	if err != nil {
		return
	}

	for _, v := range contentList {
		if v["ldap_field_name"] != "" {
			ldapFields = append(ldapFields, v)
		}
	}
	return
}

func searchRequest(username string) (userInfo *ldap.Entry, err error) {
	var (
		ldapFields       []map[string]string
		cur              *ldap.SearchResult
		ldapFieldsFilter = []string{
			"dc",
			"cn",
		}
	)
	ldapFields, err = getLdapFields()
	for _, v := range ldapFields {
		ldapFieldsFilter = append(ldapFieldsFilter, v["ldap_field_name"])
	}
	log.Info(config.C.Ldap.Binduserdn, config.C.Ldap.Bindpwd)
	// 用来获取查询权限的用户。如果 ldap 禁止了匿名查询，那我们就需要先用这个帐户 bind 以下才能开始查询
	if config.C.Ldap.Anonymousquery != "0" {
		err = conn.Bind(
			config.C.Ldap.Binduserdn,
			config.C.Ldap.Bindpwd)
		if err != nil {
			log.Error("用户或密码错误。", err)
			return
		}
	}
	filter := fmt.Sprintf("(%v=%v)", config.C.Ldap.Userfield, username)
	log.Info(config.C.Ldap.Basedn, filter, ldapFieldsFilter)
	sql := ldap.NewSearchRequest(
		config.C.Ldap.Basedn,
		ldap.ScopeWholeSubtree,
		ldap.NeverDerefAliases,
		0,
		0,
		false,
		filter,
		ldapFieldsFilter,
		nil)
	log.Info(sql)
	if cur, err = conn.Search(sql); err != nil {
		err = errors.New(fmt.Sprintf("在Ldap搜索用户失败, %v", err))
		log.Error(err)
		return
	}

	if len(cur.Entries) == 0 {
		err = errors.New("未查询到对应的用户信息。")
		log.Error(err)
		return
	}

	userInfo = cur.Entries[0]

	return
}
